import subprocess
import os
import tempfile
import threading
import time
from enum import Enum
from typing import Optional, Tuple


class JudgeResult(Enum):
    ACCEPTED = "Accepted"
    WRONG_ANSWER = "Wrong Answer"
    TIME_LIMIT_EXCEEDED = "Time Limit Exceeded"
    MEMORY_LIMIT_EXCEEDED = "Memory Limit Exceeded"
    RUNTIME_ERROR = "Runtime Error"
    COMPILE_ERROR = "Compile Error"
    SYSTEM_ERROR = "System Error"


class Judger:
    def __init__(self, time_limit: int = 1000, memory_limit: int = 65536):
        """
        初始化判断器
        
        :param time_limit: 时间限制（毫秒）
        :param memory_limit: 内存限制（KB）
        """
        self.time_limit = time_limit
        self.memory_limit = memory_limit
        self.process = None
        self.timeout_flag = False

    def _run_with_timeout(self, command: list, input_data: str = "", timeout: int = 10) -> Tuple[int, str, str]:
        """
        在超时限制内运行命令
        
        :param command: 要执行的命令
        :param input_data: 输入数据
        :param timeout: 超时时间（秒）
        :return: (return_code, stdout, stderr)
        """
        def target():
            try:
                # 对于Python程序，需要使用python命令执行
                if command[0].endswith('.py'):
                    cmd = ['python'] + command
                else:
                    cmd = command
                    
                self.process = subprocess.Popen(
                    cmd,
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    text=True
                )
                self.stdout, self.stderr = self.process.communicate(input=input_data, timeout=timeout)
            except subprocess.TimeoutExpired:
                self.timeout_flag = True
                if self.process:
                    self.process.kill()
                    self.process.wait()

        thread = threading.Thread(target=target)
        thread.start()
        thread.join(timeout)

        if thread.is_alive():
            self.timeout_flag = True
            if self.process:
                self.process.kill()
                self.process.wait()
            thread.join()

        if self.timeout_flag:
            return -1, "", "Time limit exceeded"
        
        if self.process:
            return self.process.returncode, self.stdout, self.stderr
        else:
            return -1, "", "Process creation failed"

    def judge(self, executable_path: str, input_data: str, expected_output: str) -> dict:
        """
        判断程序执行结果是否正确
        
        :param executable_path: 可执行文件路径
        :param input_data: 输入数据
        :param expected_output: 预期输出
        :return: 判断结果字典
        """
        # 检查可执行文件是否存在
        if not os.path.exists(executable_path):
            return {
                "result": JudgeResult.SYSTEM_ERROR.value,
                "message": f"Executable file not found: {executable_path}",
                "stdout": "",
                "stderr": "",
                "time_used": 0,
                "memory_used": 0
            }

        # 运行程序
        start_time = time.time()
        return_code, stdout, stderr = self._run_with_timeout(
            [executable_path],
            input_data,
            self.time_limit / 1000.0
        )
        end_time = time.time()
        time_used = (end_time - start_time) * 1000  # 转换为毫秒

        # 处理超时
        if self.timeout_flag or time_used > self.time_limit:
            return {
                "result": JudgeResult.TIME_LIMIT_EXCEEDED.value,
                "message": "Program exceeded time limit",
                "stdout": stdout,
                "stderr": stderr,
                "time_used": time_used,
                "memory_used": 0  # 简化处理，实际系统中需要监控内存使用
            }

        # 处理运行时错误
        if return_code != 0:
            return {
                "result": JudgeResult.RUNTIME_ERROR.value,
                "message": f"Program exited with code {return_code}",
                "stdout": stdout,
                "stderr": stderr,
                "time_used": time_used,
                "memory_used": 0
            }

        # 比较输出
        if self._compare_output(stdout, expected_output):
            return {
                "result": JudgeResult.ACCEPTED.value,
                "message": "Correct answer",
                "stdout": stdout,
                "stderr": stderr,
                "time_used": time_used,
                "memory_used": 0
            }
        else:
            return {
                "result": JudgeResult.WRONG_ANSWER.value,
                "message": "Output does not match expected result",
                "stdout": stdout,
                "stderr": stderr,
                "time_used": time_used,
                "memory_used": 0
            }

    def _compare_output(self, output: str, expected: str) -> bool:
        """
        比较程序输出和预期输出
        
        :param output: 程序实际输出
        :param expected: 预期输出
        :return: 是否匹配
        """
        # 移除行尾空格和末尾空行
        output_lines = [line.rstrip() for line in output.rstrip().split('\n')]
        expected_lines = [line.rstrip() for line in expected.rstrip().split('\n')]
        
        # 如果其中一个是空列表（表示空输出），则两个都应该是空的
        if not output_lines or output_lines == ['']:
            return not expected_lines or expected_lines == ['']
        
        if not expected_lines or expected_lines == ['']:
            return not output_lines or output_lines == ['']
        
        # 比较每一行
        return output_lines == expected_lines


def create_judger(time_limit: int = 1000, memory_limit: int = 65536) -> Judger:
    """
    创建一个判断器实例
    
    :param time_limit: 时间限制（毫秒）
    :param memory_limit: 内存限制（KB）
    :return: Judger实例
    """
    return Judger(time_limit, memory_limit)
